package wsi.function;

import java.io.File;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.rygh.core.xml.XmlLeaf;
import org.rygh.semantic.model.rdf.Entity;
import org.rygh.semantic.model.rdf.Predicate;
import org.rygh.semantic.sparql.SparQL;

import wsi.match.MatchProperty;
import wsi.match.MatchProperty.Threshold;
import wsi.script.AppConfig;
import wsi.script.AppTag;
import wsi.script.QueryTuple;

public class RuntimeInfo {
	private final String queryId;
	private final Function function;
	private final QueryTuple queryInfo;

	private final Predicate idPredicate;
	private final Function providerFunction;
	private final List<MatchProperty> matchProperties;

	private boolean assistNeeded = false;
	private boolean assistReady = false;

	public RuntimeInfo(Function function, XmlLeaf node) {
		this.function = function;

		String service = function.getService();

		if (node.isLeaf()) {
			AppConfig config = AppConfig.shared();

			idPredicate = null;
			matchProperties = null;
			providerFunction = null;

			queryId = node.getValue().getAttribute(AppTag.input_query);

			// System.out.println("input config function "
			// + node.getValue().getAttribute(Tag.name.name()));

			queryInfo = config.getQueryTuple(queryId);
		} else {
			queryInfo = null;
			queryId = null;

			XmlLeaf depend_node = node.getFirstChild();
			XmlLeaf func_node = depend_node.getFirstChild();

			String func_name = func_node.getValue().getAttribute(AppTag.name);

			idPredicate = new Predicate(depend_node.getValue().getAttribute(
					AppTag.id_predicate));
			providerFunction = FunctionController.shared().getFunction(service,
					func_name);

			matchProperties = new LinkedList<>();

			for (XmlLeaf i : func_node.getChildren()) {
				matchProperties
						.add(MatchProperty.getMatchProperty(i.getValue()));
			}
		}
	}

	/**
	 * all xml files have their accompanies.
	 * 
	 * @return
	 */
	public boolean checkIfAssistReady() {
		DirManager dir = new DirManager(function);

		File[] xmlfs = dir.getXmlFiles();
		File[] xmlafs = dir.getXmlAppendFiles();

		Set<String> set = new HashSet<>();

		for (File f : xmlfs)
			set.add(f.getName());

		int missing = 0;

		for (File f : xmlafs)
			if (!set.contains(f.getName())) {
				System.out
						.printf("assist file %s is not ready.\n", f.getName());

				missing++;
			}

		setAssistReady(1. * missing / set.size() < Threshold.MINORITY);
		return isAssistReady();
	}

	public Predicate getIdPredicate() {
		return idPredicate;
	}

	public Predicate getLinkPredicate() {
		return queryInfo == null ? null : queryInfo.getLinkPredicate();
	}

	public List<MatchProperty> getMatchProperties() {
		return matchProperties;
	}

	public Predicate getNamePredicate() {
		return queryInfo == null ? null : queryInfo.getNamePredicate();
	}

	public Function getProviderFunction() {
		return providerFunction;
	}

	public SparQL getQuery() {
		return queryInfo == null ? null : queryInfo.getQuery();
	}

	public String getQueryId() {
		return queryId;
	}

	public Entity getType() {
		return queryInfo == null ? null : queryInfo.getType();
	}

	public boolean isAssistNeeded() {
		return assistNeeded;
	}

	public boolean isAssistReady() {
		return assistReady;
	}

	public void setAssistNeeded(boolean assistNeeded) {
		this.assistNeeded = assistNeeded;
	}

	public void setAssistReady(boolean assistReady) {
		this.assistReady = assistReady;
	}

}
